package com.scau.database.service.aftersalesstaff;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scau.data.entity.*;
import com.scau.data.mapper.OnsellMapper;
import com.scau.data.mapper.ReturnGoodsMapper;
import com.scau.data.mapper.ShopMapper;
import com.scau.database.common.service.ImportMapperService;
import com.scau.database.entity.aftersale.manage.*;
import com.scau.database.enums.*;
import com.scau.database.exception.APIException;
import org.aspectj.weaver.ast.Or;
import org.hibernate.criterion.Order;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;


import java.util.Calendar;
import java.util.Date;

/**
 * @ClassName: AfterSalesSevice
 * @Description: TODO
 * @Author: sunslikes
 * @Date: 2020/6/23 19:37
 * @Version: 1.0
 */
@Service
public class AfterSalesService {

    @Autowired
    ImportMapperService importMapperService;

    /**
     * 处理退货
     * 验证 是否过保，查询是什么保
     * 如果可以重新销售，则发还原商家
     * 如果不可以，则发还工厂销毁
     * @param goodsVO 退货商品
     * @return
     */
    @Transactional
    public ResponseReturnGoodsVO returnGoods(ReturnGoodsVO goodsVO) {
        // 获取dto，验证都交给这个了
        GoodsDTO goodsDTO = getGoodsDTO(goodsVO.getShopId(),goodsVO.getBarCode(), AfterSalesTypeEnum.RETURN);
        // 判断数量是否超标
        if (goodsVO.getCount() > goodsDTO.getShopLineDO().getCount()) {
            throw new APIException("您输入的数量有误！");
        }
        ReturnGoodsDO returnGoodsDO = new ReturnGoodsDO();
        returnGoodsDO.setOrderNumber(goodsDTO.getShopLineDO().getOrderNumber());
        // 上架流水号
        returnGoodsDO.setShelfId(goodsDTO.getShopLineDO().getShelfId());
        /**
         * 赋值
         * 关于赋值可以使用BeanUtils和PropertyUtils的copyProperties
         * 二者对于类中属性的null元素处理方式不同，PropertyUtils会对部分值进行初始化
         */
        BeanUtils.copyProperties(goodsVO, returnGoodsDO);
        returnGoodsDO.setFinished(IsFinishedEnum.NOT_FINISHED.getType());
        returnGoodsDO.setTime(goodsDTO.getNowData());
        returnGoodsDO.setType(String.valueOf(ReturnGoodsTypeEnum.FACTORY.getType()));
        // 售后类型
        switch (goodsDTO.getGoodsProtectionTypeEnum()) {
            case STORE:
                returnGoodsDO.setTime(goodsDTO.getNowData());
                returnGoodsDO.setType(String.valueOf(ReturnGoodsTypeEnum.STORE.getType()));
                break;
            case FACTORY:
                returnGoodsDO.setTime(goodsDTO.getNowData());
                returnGoodsDO.setType(String.valueOf(ReturnGoodsTypeEnum.FACTORY.getType()));
                break;
        }
        ResponseReturnGoodsVO responseReturnGoodsVO = new ResponseReturnGoodsVO();
        StoreDO storeDO = importMapperService.storeMapper.selectById(goodsDTO.getSalesStoreId());
        if (storeDO == null) {
            throw new APIException("没有这家商家");
        }
        responseReturnGoodsVO.setStoreName(storeDO.getName());
        responseReturnGoodsVO.setStoreAddr(storeDO.getAddress());
        responseReturnGoodsVO.setStoreLeader(storeDO.getLeader());
        // 可以二次销售的都进了兄弟店继续卖
        if (goodsVO.getCanResell()) {
            resellGoods(goodsDTO, goodsVO.getCount());
            returnGoodsDO.setFinished(IsFinishedEnum.IS_FINISHED.getType());
        } else {
            // 不能的交给工厂去销毁
            returnGoodsDO.setFinished(IsFinishedEnum.NOT_FINISHED.getType());
            Integer warehouseId = importMapperService.returnGoodsMapper.getWarehouseId(goodsDTO.getShopLineDO().getShelfId());
            QueryWrapper<WareHouseDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", warehouseId);
            WareHouseDO wareHouseDO = importMapperService.wareHouseMapper.selectOne(queryWrapper);
            responseReturnGoodsVO.setWarehouseAddr(wareHouseDO.getAddress());
        }
        // 减掉响应的退货数量
        importMapperService.shopLineMapper.update(null, Wrappers.<ShopLineDO>lambdaUpdate()
                .eq(ShopLineDO::getShopId, goodsDTO.getShopLineDO().getShopId())
                .set(ShopLineDO::getCount, goodsDTO.getShopLineDO().getCount() - goodsVO.getCount()));
        importMapperService.returnGoodsMapper.insert(returnGoodsDO);
        return responseReturnGoodsVO;
    }

    /**
     * 换货 ,直接交货的那种
     * 厂保
     *  则直接提醒申请延期交付，发送厂订单
     * 店保
     * @param goodsVO
     * @return
     */
    @Transactional
    public String exchangeGoods(ExchangeGoodsVO goodsVO) {
        GoodsDTO goodsDTO = getGoodsDTO(goodsVO.getShopId(), goodsVO.getBarCode(), AfterSalesTypeEnum.EXCHANGE);
        if (goodsVO.getCount() > goodsDTO.getShopLineDO().getCount()) {
            throw new APIException("您输入的数量有误！");
        }
        ExchangeGoodsDO exchangeGoodsDO = new ExchangeGoodsDO();
        BeanUtils.copyProperties(goodsVO, exchangeGoodsDO);
        exchangeGoodsDO.setOrderNumber(goodsDTO.getShopLineDO().getOrderNumber());
        exchangeGoodsDO.setShelfId(goodsDTO.getShopLineDO().getShelfId());
        switch (goodsDTO.getGoodsProtectionTypeEnum()) {
            case FACTORY:
                //厂保
                throw new APIException("厂保期间请申请延期交付");
            case STORE:
                //店保
                if (!goodsDTO.getSalesStoreId().equals(goodsVO.getServiceId())) {
                    throw new APIException("已过厂保，店保产品请到原购买店。");
                }
                exchangeGoodsDO.setType(ExchangeGoodsTypeEnum.EXCHANGE_STORE.getType());
                // 查询是否有货
                OnSellDO onSellDOCondition = new OnSellDO();
                onSellDOCondition.setStoreId(goodsVO.getServiceId());
                onSellDOCondition.setBarCode(goodsVO.getBarCode());
                OnSellDO onSellDO = importMapperService.onsellMapper.selectOne(new QueryWrapper<>(onSellDOCondition).last("limit 1"));
                if (onSellDO == null) {
                    throw new APIException("错误请求");
                } else if (onSellDO.getSurplus() < goodsVO.getCount()) {
                    return "shop_owe";
                }
                //
                if (!goodsVO.getCanResell()) {
                    onSellDO.setSurplus(onSellDO.getSurplus() - goodsVO.getCount());
                    QueryWrapper<ShelfOKDO> shelfOKDOQueryWrapper = new QueryWrapper<>();
                    shelfOKDOQueryWrapper.eq("store_id", goodsVO.getServiceId())
                            .eq("bar_code", goodsDTO.getShopLineDO().getBarCode()).last("limit 1");
                    ShelfOKDO shelfOKDO = importMapperService.shelfOKMapper.selectOne(shelfOKDOQueryWrapper);
                    if (shelfOKDO == null) {
                        throw new APIException("上架表中无足够库存商品");
                    }
                    shelfOKDO.setSurplus(shelfOKDO.getSurplus() - goodsVO.getCount());
                    importMapperService.onsellMapper.update(null, Wrappers.<OnSellDO>lambdaUpdate()
                                                                            .eq(OnSellDO::getStoreId, onSellDO.getStoreId())
                                                                                .eq(OnSellDO::getBarCode, onSellDO.getBarCode())
                                                                                    .set(OnSellDO::getSurplus, onSellDO.getSurplus()));
                    importMapperService.shelfOKMapper.updateById(shelfOKDO);
                    importMapperService.exchangeGoodsMapper.insert(exchangeGoodsDO);
                }
                break;
        }
        return "ok";
    }

    /**
     *
     * @param goodsVO
     * @return
     */
    @Transactional
    public String repairGoods(RepairGoodsVO goodsVO) {
        GoodsDTO goodsDTO = getGoodsDTO(goodsVO.getShopId(), goodsVO.getBarCode(), AfterSalesTypeEnum.EXCHANGE);
        // 维修方式选择
        if (goodsVO.getRepairType().equals(RepairGoodsTypeEnum.FACTORY.getType().toString())) {
            RepairGoodsDO repairGoodsDO = new RepairGoodsDO();
            BeanUtils.copyProperties(goodsVO, repairGoodsDO);
            repairGoodsDO.setTime(new Date());
            RepairGoodsFactoryDO factoryDO = new RepairGoodsFactoryDO();
            BeanUtils.copyProperties(repairGoodsDO, factoryDO);
            OrderDO orderDOCondition = new OrderDO();
            orderDOCondition.setOrderNumber(goodsDTO.getShopLineDO().getOrderNumber());
            Integer warehouseId = importMapperService.returnGoodsMapper.getWarehouseId(goodsDTO.getShopLineDO().getShelfId());
            orderDOCondition.setWarehouseId(warehouseId);
            OrderDO orderDO = importMapperService.orderMapper.selectOne(new QueryWrapper<>(orderDOCondition).last("limit 1"));
            if (orderDO == null) {
                throw new APIException("订单错误！");
            }
            Integer factoryId = orderDO.getFactoryId();
            factoryDO.setFactoryId(factoryId);
            importMapperService.repairGoodsFactoryMapper.insert(factoryDO);
            repairGoodsDO.setRepairId(factoryDO.getId());
            importMapperService.repairGoodsMapper.insert(repairGoodsDO);
            // 减掉响应的维修数量
            importMapperService.shopLineMapper.update(null, Wrappers.<ShopLineDO>lambdaUpdate()
                    .eq(ShopLineDO::getShopId, goodsDTO.getShopLineDO().getShopId())
                    .set(ShopLineDO::getCount, goodsDTO.getShopLineDO().getCount() - 1));
            return "ok";
        } else if (goodsVO.getRepairType().equals(RepairGoodsTypeEnum.OTHER.getType().toString())) {
            // 第三方维修
            RepairGoodsDO repairGoodsDO = new RepairGoodsDO();
            BeanUtils.copyProperties(goodsVO, repairGoodsDO);
            repairGoodsDO.setTime(new Date());
            QueryWrapper<RepairStoreDO> storeDOQueryWrapper = new QueryWrapper<>();
            RepairStoreDO repairStoreDO = importMapperService.repairStoreMapper.selectOne(storeDOQueryWrapper.last("limit 1"));
            RepairGoodsStoreDO repairGoodsStoreDO = new RepairGoodsStoreDO();
            BeanUtils.copyProperties(repairGoodsDO, repairGoodsStoreDO);
            repairGoodsStoreDO.setRepairStoreId(repairStoreDO.getId());
            importMapperService.repairGoodsStoreMapper.insert(repairGoodsStoreDO);
            repairGoodsDO.setRepairId(repairGoodsStoreDO.getId());
            importMapperService.repairGoodsMapper.insert(repairGoodsDO);
            // 减掉响应的维修数量
            importMapperService.shopLineMapper.update(null, Wrappers.<ShopLineDO>lambdaUpdate()
                    .eq(ShopLineDO::getShopId, goodsDTO.getShopLineDO().getShopId())
                    .set(ShopLineDO::getCount, goodsDTO.getShopLineDO().getCount() - 1));
            return "第三方维修点电话："  + repairStoreDO.getPhone();
        } else {
            throw new APIException("参数有误");
        }
    }

    /**
     * 搜索卖货表获取进货号和上架号
     * @param shopId
     * @param barCode
     * @return
     */
    private ShopLineDO getShopLineDOByShopIDAndBarCode(Long shopId, String barCode) {
        ShopLineDO shopLineDOCondition = new ShopLineDO();
        shopLineDOCondition.setBarCode(barCode);
        shopLineDOCondition.setShopId(shopId);
        ShopLineDO shopLineDO = importMapperService.shopLineMapper.selectOne(new QueryWrapper<>(shopLineDOCondition));
        return shopLineDO;
    }

    /**
     * 厂保时间：通过选择的售后类型获取剩余时间
     * @param barCode 条形码
     * @param typeEnum 售后类型
     * @return
     */
    private Integer getFactoryServiceDays(String barCode, AfterSalesTypeEnum typeEnum) {
        CommodityInfoDO commodityInfoDOCondition = new CommodityInfoDO();
        commodityInfoDOCondition.setBarCode(barCode);
        CommodityInfoDO infoDO = importMapperService.commodityInfoMapper.selectOne(new QueryWrapper<>(commodityInfoDOCondition));
        if (infoDO == null) {
            return null;
        }
        switch (typeEnum) {
            case RETURN:
                return infoDO.getReturnDays();
            case REPAIRE:
                return infoDO.getRepairDays();
            case EXCHANGE:
                return infoDO.getExchangeDays();
        }
        return null;
    }

    /**
     * 店保时间：通过on_sell查询
     * @param storeId
     * @param barCode
     * @param typeEnum
     * @return
     */
    private Integer getShopServiceDays(Integer storeId, String barCode, AfterSalesTypeEnum typeEnum) {
        QueryWrapper<OnSellDO> onSellDOQueryWrapper = new QueryWrapper<>();
        onSellDOQueryWrapper.eq("store_id", storeId)
                .eq("bar_code", barCode);
        OnSellDO onSellDO = importMapperService.onsellMapper.selectOne(onSellDOQueryWrapper);
        if (onSellDO == null) {
            throw new APIException("没有这笔订单！");
        }
        switch (typeEnum) {
            case EXCHANGE:
                return onSellDO.getExchangeDays();
            case REPAIRE:
                return onSellDO.getRepairDays();
            case RETURN:
                return onSellDO.getReturnDays();
        }
        return null;
    }

    /**
     * 比较新和老时间是不是相差在允许的时间内
     * 验证也都在这里，有问题直接抛出异常
     * @param old
     * @param newd
     * @param days
     * @return
     */
    private Boolean compareTheDates(Date old, Date newd, Integer days) {
        float result = (float) ((newd.getTime() - old.getTime())/24/3600/1000 * 1.0 - 1.0 * days);
        return result<0? true:false;
    }

    /**
     * 返回goodsDTO，并对订单号和条形码以及服务时间进行验证
     * @param shopId
     * @param barCode
     * @param typeEnum
     * @return
     */
    public GoodsDTO getGoodsDTO(Integer shopId, String barCode, AfterSalesTypeEnum typeEnum) {
        Date now = new Date();
        // 验证有没有这笔订单，以及获取购买时间
        ShopDO shopDOCondition = new ShopDO();
        shopDOCondition.setId(Long.valueOf(shopId));
        ShopDO shopDO = importMapperService.shopMapper.selectOne(new QueryWrapper<>(shopDOCondition));
        // 说明没有这笔订单
        if (shopDO == null) {
            throw new APIException("没有这笔订单");
        }
        Date buyDate = shopDO.getTime();
        // 查询是否过期
        // 通过售后时间判断过了店保和厂保没，优先厂保
        Integer factoryServiceDays = getFactoryServiceDays(barCode, typeEnum);
        Integer shopServiceDays = getShopServiceDays(shopDO.getStoreId(), barCode, typeEnum);
        if (factoryServiceDays == null || shopServiceDays == null) {
            throw new APIException("没有这个商品");
        }
        // 保存类型
        GoodsProtectionTypeEnum goodsProtectionTypeEnum;
        if (compareTheDates(buyDate, now, factoryServiceDays)) {
            goodsProtectionTypeEnum = GoodsProtectionTypeEnum.FACTORY;
        } else if(compareTheDates(buyDate, now, shopServiceDays)) {
            goodsProtectionTypeEnum = GoodsProtectionTypeEnum.STORE;
        } else {
            throw new APIException("已过" + typeEnum.getDescription() + "时间");
        }
        // 搜索卖货表获取进货号和上架号，顺便验证有没有这笔订单
        ShopLineDO shopLineDO = getShopLineDOByShopIDAndBarCode(Long.valueOf(shopId), barCode);
        if (shopLineDO == null) {
            throw new APIException("无此订单！");
        }
        GoodsDTO goodsDTO = new GoodsDTO();
        goodsDTO.setNowData(now);
        goodsDTO.setSalesStoreId(shopDO.getStoreId());
        goodsDTO.setGoodsProtectionTypeEnum(goodsProtectionTypeEnum);
        goodsDTO.setShopLineDO(shopLineDO);
        return goodsDTO;
    }

    /**
     * 可以再销售产品
     * @param dto
     * @param count
     */
    public void resellGoods(GoodsDTO dto, Integer count) {
        importMapperService.onsellMapper.addSurplus(dto.getSalesStoreId(), dto.getShopLineDO().getBarCode(), count);
        ShelfOKDO shelfOKDO = importMapperService.shelfOKMapper.selectById(dto.getShopLineDO().getShelfId());
        if (shelfOKDO != null) {
            shelfOKDO.setSurplus(shelfOKDO.getSurplus() + count);
        } else {
            // 说明已经卖完了，从卖完的里面取出再卖
            ShelfOverDO shelfOverDO = importMapperService.shelfOverMapper.selectById(dto.getShopLineDO().getShelfId());
            BeanUtils.copyProperties(shelfOverDO, shelfOKDO);
            shelfOKDO.setSurplus(count);
            importMapperService.shelfOverMapper.deleteById(dto.getShopLineDO().getShelfId());
            importMapperService.shelfOKMapper.insert(shelfOKDO);
        }
    }


}
